#!/usr/bin/env python3

# Written by Rifki K.

from prompt_toolkit import print_formatted_text, HTML
from prompt_toolkit import prompt
from random import randint


def main():
    pass


if __name__ == '__main__':
    main()


class Character:
    def __init__(self):
        self.name = ""
        self.health = 1
        self.health_max = 1

    def do_damage(self, enemy):
        damage = min(
            max(randint(0, self.health) - randint(0, enemy.health), 0),
            enemy.health)
        enemy.health = enemy.health - damage
        if damage == 0:
            print_formatted_text(HTML("<ansigreen>%s evades %s's attack.</ansigreen>" % (enemy.name, self.name)))
        else:
            print_formatted_text(HTML("<ansired>%s hurts %s!</ansired>" % (self.name, enemy.name)))
        return enemy.health <= 0


class Enemy(Character):
    def __init__(self, player):
        Character.__init__(self)
        self.name = 'a goblin'
        self.health = randint(1, player.health)


class Player(Character):
    def __init__(self):
        Character.__init__(self)
        self.state = 'normal'
        self.health = 10
        self.health_max = 10

    def quit(self):
        print_formatted_text(HTML(
            "<ansired>%s can't find the way back home, and dies of starvation.\nR.I.P.</ansired>" % self.name))
        self.health = 0

    def help(self): print_formatted_text(list(Commands.keys()))
    def status(self): print_formatted_text("%s's health: %d/%d" %
                            (self.name, self.health, self.health_max))

    def tired(self):
        print_formatted_text("%s feels tired." % self.name)
        self.health = max(1, self.health - 1)

    def rest(self):
        if self.state != 'normal':
            print_formatted_text("%s can't rest now!" % self.name)
            self.enemy_attacks()
        else:
            print_formatted_text("%s rests." % self.name)
            if randint(0, 1):
                self.enemy = Enemy(self)
                print_formatted_text(HTML("<ansired>%s is rudely awakened by %s!</ansired>" %
                      (self.name, self.enemy.name)))
                self.state = 'fight'
                self.enemy_attacks()
            else:
                if self.health < self.health_max:
                    self.health = self.health + 1
                else:
                    print_formatted_text("%s slept too much." % self.name)
                    self.health = self.health - 1

    def explore(self):
        if self.state != 'normal':
            print_formatted_text("%s is too busy right now!" % self.name)
            self.enemy_attacks()
        else:
            print_formatted_text("%s explores a twisty passage." % self.name)
            if randint(0, 1):
                self.enemy = Enemy(self)
                print_formatted_text(HTML("<yellow>%s encounters %s!</yellow>" % (self.name, self.enemy.name)))
                self.state = 'fight'
            else:
                if randint(0, 1):
                    self.tired()

    def flee(self):
        if self.state != 'fight':
            print_formatted_text("%s runs in circles for a while." % self.name)
            self.tired()
        else:
            if randint(1, self.health + 5) > randint(1, self.enemy.health):
                print_formatted_text(HTML("<deepskyblue>%s flees from %s.</deepskyblue>" % (self.name, self.enemy.name)))
                self.enemy = None
                self.state = 'normal'
            else:
                print_formatted_text("<yellow>%s couldn't escape from %s!</yellow>" %
                      (self.name, self.enemy.name))
                self.enemy_attacks()

    def attack(self):
        if self.state != 'fight':
            print_formatted_text("%s swats the air, without notable results." % self.name)
            self.tired()
        else:
            if self.do_damage(self.enemy):
                print_formatted_text(HTML("<ansired>%s executes %s!</ansired>" % (self.name, self.enemy.name)))
                self.enemy = None
                self.state = 'normal'
                if randint(0, self.health) < 10:
                    self.health = self.health + 1
                    self.health_max = self.health_max + 1
                    print_formatted_text(HTML("<ansigreen>%s feels stronger!</ansigreen>" % self.name))
            else:
                self.enemy_attacks()

    def enemy_attacks(self):
        if self.enemy.do_damage(self):
            print_formatted_text(HTML("<ansired>%s was slaughtered by %s!!!\nR.I.P.</ansired>" %
                  (self.name, self.enemy.name)))


Commands = {
    'quit': Player.quit,
    'help': Player.help,
    'status': Player.status,
    'rest': Player.rest,
    'explore': Player.explore,
    'flee': Player.flee,
    'attack': Player.attack,
}

p = Player()
p.name = prompt("What is your character's name? ")
print_formatted_text("(type help to get a list of actions)\n")
print_formatted_text(HTML("<deepskyblue>%s enters a dark cave, searching for adventure.</deepskyblue>" % p.name))

while(p.health > 0):
    line = prompt("> ").lower()
    args = line.split()
    if len(args) > 0:
        commandFound = False
        for c in list(Commands.keys()):
            if args[0] == c[:len(args[0])]:
                Commands[c](p)
                commandFound = True
                break
        if not commandFound:
            print_formatted_text(HTML("<yellow>%s doesn't understand the suggestion.</yellow>" % p.name))
